#include "server.h"

#ifdef _WIN32
char *DEVNULL = "nul";
#endif

#ifdef __APPLE__
char *DEVNULL = "/dev/null";
#endif

#ifdef __linux__
char *DEVNULL = "/dev/null";
#endif

volatile sig_atomic_t CONTINUE_SERVER = 1;

/**
 * @fn void *routineThread_Server(void *arg)
 * @brief Fonction éffectuer par les threads de services.
 *
 * C'est une boucle qui se termine lorsque le client termine la transaction ou lorsque le serveur se ferme.
 * @param arg L'argument de la fonction, qui correspond au serveur.
 * @return NULL pour le moment.
 */
void *routineThread_Server(void *arg);

void *routineThreadClient_Server(void *arg);

/**
 * @fn ServerReturn beginingDealing_Server(int socket)
 * @brief Commence la transaction avec le client.
 *
 * La transaction commence par le mot "HELO\n" puis les différentes commande.
 * @param socket La socket du clie
 * @param[in,out] mutexFile Le mutex permettant de gérer les fichiers utilisés par les clients.
 * @return SERVER_SUCCESS ou SERVER_QUIT ou SERVER_CON_ERR.
 */
ServerReturn beginingDealing_Server(int socket, MutexFile *mutexFile, char *folder);

/**
 * @fn ServerReturn waitOrder_Server(int socket)
 * @brief Fonction de réception d'une commande d'un client. La fonction traite ensuite la commande.
 *
 * @param socket La socket du client.
 * @param[in,out] mutexFile Le mutex sur les fichiers utilisés par les clients.
 * @return SERVER_QUIT pour finir la transaction, SERVER_ERR en cas d'erreur et SERVER_SUCCESS sinon.
 */
ServerReturn waitOrder_Server(int socket, MutexFile *mutexFile, char *folder);

/**
 * @fn ServerClientOrder orderString_Server(const char *reception)
 * @brief Fonction qui teste la commande du client et qui renvoie son type défini dans l'enum ServerClientOrder.
 *
 * @param reception La commande à analyser.
 * @return Le type de la commande et FAIL si la commande n'existe pas.
 */
ServerClientOrder orderString_Server(const char *reception);

/**
 * @fn ServerReturn sendList_Server(int socket, const char *folder)
 * @brief Fonction qui envoie la liste des fichiers en terminant par "ENDL\n".
 *
 * @param socket La socjet du client.
 * @param folder Le dossier à lister.
 * @return SERVER_SUCCESS en cas de succès et SERVER_ERR sinon.
 */
ServerReturn sendList_Server(int socket, const char *folder);

/**
 * @fn ServerReturn sendList_Server(int socket, const char *folder)
 * @brief Fonction qui le fichier au client. NONE si le fichier n'existe pas et FAIL si il n'y a pas de fichier dans la commande.
 *
 * @param socket La socket du client.
 * @param reception La commande qui commence par GETF
 * @param[in,out] mutexFile Le mutex sur les fichiers utilisés par les clients.
 * @return SERVER_SUCCESS en cas de succès et SERVER_ERR sinon.
 */
ServerReturn sendGetF_Server(int socket, char *reception, MutexFile *mutexFile, char *file);

/**
 * @fn ServerReturn sendFile_Server(int socket, const char *file)
 * @brief Fonction qui envoie n'importe quel type de fichier au client.
 *
 * @param socket La socket du client.
 * @param file Le fichier à envoyer.
 * @return SERVER_SUCCESS pour la réussite. SERVER_ERR si il y a eu un problème sur le fichier et SERVER_CON_ERR en cas d'erreur lors de l'envoie.
 */
ServerReturn sendFile_Server(int socket, const char *file);

/**
 * @fn ServerReturn receiveFree_Server(int socket, char *reception, MutexFile *mutexFile)
 * @brief Fonction qui libère un fichier de la liste mutexFile.
 *
 * @param socket La socket du client.
 * @param[in,out] reception Le fichier à libérer.
 * @param[in,out] mutexFile La liste qui doit contenir le fichier.
 * @return SERVER_SUCCESS pour la réussite. SERVER_ERR si le fichier n'existe pas.
 */
ServerReturn receiveFree_Server(int socket, char *reception, MutexFile *mutexFile, char *file);

void server(const int nbThread, const char * port, const char *folder, const int nbSocketAttente)
{
  Server server;
  fd_set rfds, rfds_tot;
  int socketClient;
  int i;
  int ret = 'A';
  pthread_t threadClient;
  /* Création de la socket d'écoute */
  server.socket = creationSocket_Server(port);

  server.port = (char *) malloc ((1 + strlen(port)) * sizeof(char));
  strcpy(server.port, port);
  server.nbThread = nbThread;
  server.tabThread = (pthread_t *) malloc (nbThread * sizeof(pthread_t));
  server.nbSocketAttente = nbSocketAttente;
  if(server.tabThread == NULL)
    {
      fprintf(stderr, "[server]Erreur allocation du tableau de thread\n");
      exit(1);
    }
  server.folder = (char *) malloc (( 1 + strlen(folder)) * sizeof(char));
  strcpy(server.folder, folder);

  /* Initialisation de la structure de Mutex */
  initialize_MutexList(&(server.mutexList), nbSocketAttente);
  initialize_MutexFile(&(server.mutexFile));

  /* Création de la socket de dialogue entre les threads */
  if (socketpair(AF_UNIX, SOCK_STREAM, 0, server.socketpair) < 0) {
    perror("[server]Erreur ouverture socket pair 1");
    exit(1);
  }
  /* Création de la socket de dialogue entre le thread client */
  if (socketpair(AF_UNIX, SOCK_STREAM, 0, server.socketpairClient) < 0) {
    perror("[server]Erreur ouverture socket pair 2");
    exit(1);
  }
  if (socketpair(AF_UNIX, SOCK_STREAM, 0, server.socketpairService) < 0) 
    {
      perror("[server]Erreur ouverture socket pair 3");
      exit(1);
    }
  if(pthread_create(&threadClient, NULL, routineThreadClient_Server, &server) != 0)
    {
      fprintf(stderr, "[server]Erreur création thread client\n");
      exit(1);
    }
  /* Création des différents thread */
  for(i = 0; i < nbThread; i++)
    {
      if(pthread_create(&(server.tabThread[i]), NULL, routineThread_Server, &server) != 0)
	{
	  fprintf(stderr, "[server]Erreur création du thread : %d\n", i);
	  exit(1);
	}
    }
  
  /* Initialisation des fd sur stdin et sur la socket dans le fd_set */
  FD_ZERO(&rfds_tot);
  FD_SET(server.socket, &rfds_tot);
  FD_SET(STDIN_FILENO, &rfds_tot);
  /* Boucle principal de traitement sur la socket de connexion et sur l'entrée standard */
  while(ret != 'S' && ret != 's' && CONTINUE_SERVER)
    {
      int retval;
      FD_ZERO(&rfds);
      rfds = rfds_tot;
      retval = select(FD_SETSIZE, &rfds, NULL, NULL, NULL);
      if(retval == -1)
	{
	  perror("[server]Erreur select");
	  exit(1);
	}
      if(FD_ISSET(server.socket, &rfds))
	{
	  socketClient = attenteConnexion_Server(server.socket);
	  if(send(server.socketpairClient[1], &socketClient, sizeof(int), 0) == -1)
	    {
	      fprintf(stderr, "[server]Erreur socketpairClient\n");
	      CONTINUE_SERVER = 0;
	    }
	}
      if(FD_ISSET(STDIN_FILENO, &rfds))
	{
	  ret = getchar();
	  while(getchar() != '\n');
	}
    }
  /* Arrêt des threads */
  CONTINUE_SERVER = 0;
  /* On le dit aux threads de service */
  i = -1;
  if(write(server.socketpairClient[1], &i, sizeof(int)) < 0)
    {
      perror("[server]Erreur socketpairClient");
    }

  /* On le dit aux threads de service */
  if(write(server.socketpair[1], "QUIT", 4 * sizeof(char)) < 0)
    {
      perror("[server]Erreur socketpair");
    }
  /* Fin du server (la lettre S à été taper) */
  fprintf(stderr, "(server)Fermeture du serveur...\n");
  fflush(stdout);
  /* Terminaison des threads en attente de connexion */
  notifyEnd_MutexList(&(server.mutexList));

  /* Attente de tout les threads pour qu'il puisse terminer leurs transaction correctement */
  for(i = 0; i < nbThread; i++)
    {
      if(pthread_join(server.tabThread[i], NULL) != 0)
	{
	  perror("[server]Erreur attente thread");
	}
    }
  if(pthread_join(threadClient, NULL) != 0)
    {
      perror("[serveur]Erreur attente thread client");
    }
  /* Libération  des resources utilisées */
  testament_MutexList(&(server.mutexList));
  testament_MutexFile(&(server.mutexFile));
  /* Fermeture de la socket d'attente de connexion */
  free(server.port);
  free(server.tabThread);
  free(server.folder);
  close(server.socket);
  fprintf(stdout, "Bye ;)\n");
}

int creationSocket_Server(const char * port) {
  struct addrinfo hints;
  struct addrinfo * result, * rp;
  int res, bon, sock_err, s;

  memset(&hints, 0, sizeof(struct addrinfo));
  hints.ai_family = AF_INET;
  hints.ai_socktype = SOCK_STREAM;
  hints.ai_flags = AI_PASSIVE;

  res = getaddrinfo(NULL, port, &hints, &result);
  if(res != 0)
    {
      fprintf(stderr, "[createSocket]getaddinfo:%s\n",gai_strerror(res));
      exit(1);
    }

  bon = 0;
  for( rp = result; rp != NULL; rp = rp->ai_next){
    s = socket (rp->ai_family, rp->ai_socktype, rp->ai_protocol);
    if( s == -1)
      {
	fprintf(stderr, "[createSocket]Création de la socket impossible\n");
	continue;
      }
    res = bind(s , rp->ai_addr, rp->ai_addrlen);
    if (res == 0)
      {
	bon = 1;
	break;
      }
    fprintf(stderr, "[createSocket]Impossible de réserver l'adresse\n");
    close(s);
  }
  freeaddrinfo(result);
  if (bon == 0)
    {
      fprintf(stderr, "[createSocket]Impossible d'obtenir une adresse\n");
      exit(1);
    }

  sock_err = listen(s, 5);

  if(sock_err == -1)
    {
      perror("listen");
      close(s);
      exit(1);
    }

  return s;
}

int attenteConnexion_Server(int socket)
{
  int t, res;
  struct sockaddr_storage taddr;
  socklen_t taddrlen = sizeof(taddr);
  char hname[NI_MAXHOST], sname [NI_MAXSERV];

  t = accept(socket, (struct sockaddr *)&taddr, &taddrlen);
  res = getnameinfo((struct sockaddr *)&taddr, taddrlen,
		    hname, NI_MAXHOST,
		    sname, NI_MAXSERV,
		    NI_NUMERICSERV);
  if(res !=0) {
    fprintf(stderr, "[waitConnection]getnameinfo : %s\n", gai_strerror(res));
    exit(1);
  }

  return t;
}

ServerReturn select_Server(int socket, int *socketpair)
{
  fd_set rfds;
  int ret;
  FD_ZERO(&rfds);
  FD_SET(socket, &rfds);
  FD_SET(socketpair[0], &rfds);
  ret = select(FD_SETSIZE, &rfds, NULL, NULL, NULL);
  
  if(ret == -1)
    {
      perror("[selectServer]Erreur select");
      return SERVER_ERR;
    }
  if(FD_ISSET(socket, &rfds))
    return SERVER_SOCKET;
  if(FD_ISSET(socketpair[0], &rfds))
    {
      return SERVER_QUIT;
    }
  return SERVER_ERR;
}

void *routineThreadClient_Server(void *arg)
{
  Server *server = (Server *)arg;
  int * socketpair = server->socketpairClient;
  int * socketpairService = server->socketpairService;
  MutexList *mutexList = &(server->mutexList);
  fd_set rfds_tot;
  fd_set rfds;
  List l;
  initialize_List(&l, create_IntList, delete_IntList, NULL, NULL);
  FD_ZERO(&rfds_tot);
  FD_SET(socketpair[0], &rfds_tot);
  FD_SET(socketpairService[0], &rfds_tot);
  while(CONTINUE_SERVER)
    {
      int ret;
      int nbSet = 0;
      rfds = rfds_tot;
      ret = select(FD_SETSIZE, &rfds, NULL, NULL, NULL);
      if(ret == -1)
	{
	  perror("[routineThreadClient]Erreur select");
	  exit(1);
	}
      if(FD_ISSET(socketpairService[0], &rfds))
	{
	  int s = -1;
	  nbSet ++;
	  while(recv(socketpairService[0], &s, sizeof(int), MSG_DONTWAIT) != -1)
	    {
	      if(s != -1)
		{
		  insertFirst_List(&l, &s);
		  FD_SET(s, &rfds_tot);
		}
	    }
	}
      if(FD_ISSET(socketpair[0], &rfds))
	{
	  int s = -1;
	  nbSet ++;
	  if(recv(socketpair[0], &s, sizeof(int), 0) == -1)
	    {
	      fprintf(stderr, "[routineThreadClient]Erreur recv socketpair\n");
	    }
	  if(s != -1)
	    {
	      if(getConnection_MutexList(mutexList) == MUTEXLIST_SUCCESS)
		{
		  char *msg = "HELO\n";
		  if(send_ToolsCS(s, msg) != TOOLSCSRETURN_SUCCESS)
		    {
		      fprintf(stderr, "[routineThreadClient]Erreur send_Tools HELO\n");
		      shutdown(s, SHUT_RDWR);
		      close(s);
		    }
		  else
		    {
		      int rML;
		      rML = insert_MutexList(mutexList, &s);
		      addConnection_MutexList(mutexList);
		      if(rML == MUTEXLIST_ERR)
			{
			  fprintf(stderr, "[routineThreadClient]Erreur inset_MutexList HELO\n");
			  CONTINUE_SERVER = 0;
			}

		      /** Pour passer les tests, je met directement la nouvelle connexion dans les threads de services. Sinon je ne passe pas certain timeout... et oui on fait comme on peut après 5 heures de recherche d'optimisation sur cette fonction.
		      insertFirst_List(&l, &s);
		      FD_SET(s, &rfds_tot);
		      */
		    }
		}
	      else
		{
		  fprintf(stderr, "(routineThreadClient)Information client rejetè car trop de connexion.\n");
 		  if(send_ToolsCS(s, "FAIL\n") != TOOLSCSRETURN_SUCCESS)
		    {
		      fprintf(stderr, "[routineThreadClient]Erreur send_ToolsCS FAIL\n");
		    }
		  shutdown(s, SHUT_RDWR);
		  close(s);
		}
	    }
	}
      if(getSize_List(&l) > 0 && nbSet < ret)
	{
	  int lRet;
	  first_List(&l);

	  do
	    {
	      int *s = getDataCurrent_List(&l);
	      if(FD_ISSET((*s), &rfds))
		{
		  int rML;
		  int tmp = (*s);
		  nbSet ++;
		  rML = insert_MutexList(mutexList, &tmp);
		  deleteCurrent_List(&l);
		  FD_CLR(tmp, &rfds_tot);
		  if(rML == MUTEXLIST_ERR)
		    {
		      fprintf(stderr, "[routineThreadClient]Erreur inset_MutexList\n");
		      CONTINUE_SERVER = 0;
		    }
		}
	      lRet = next_List(&l);
	    }
	  while((lRet == LIST_SUCCESS || lRet == LIST_CUR_FIRST) && nbSet < ret);
	}
    }
  if(getSize_List(&l) > 0)
    {
      first_List(&l);
      do
	{
	  int *s = getDataCurrent_List(&l);
	  close(*s);
	}
      while(next_List(&l) == LIST_SUCCESS);
    }
  fprintf(stderr, "[routineThreadClient]Information fin\n");
  testament_List(&l);
  return NULL;
}

void *routineThread_Server(void *arg)
{
  Server *server = (Server *)arg;
  MutexList *mutexList = &(server->mutexList);
  MutexFile *mutexFile = &(server->mutexFile);
  int socket = -1;
  char *folder = server->folder;

  while(CONTINUE_SERVER)
    {
      socket = getFirst_MutexList(mutexList);
      if(socket < 0)
	{
	  /* Gestion d'erreur de MutexQueue */
	    return NULL;
	}
      if(beginingDealing_Server(socket, mutexFile, folder) == SERVER_SUCCESS)
	{
	  if(send(server->socketpairService[1], &socket, sizeof(int), 0) == -1)
	    {
	      fprintf(stderr, "[routineThread]Erreur send socketpairService\n");
	      CONTINUE_SERVER = 0;
	    } 
	}
      else
	subtractConnection_MutexList(mutexList);
    }
  return NULL;
}

ServerReturn beginingDealing_Server(int socket, MutexFile *mutexFile, char *folder)
{
  char *msg = "HELO\n";

  if(CONTINUE_SERVER)
    {
      ServerReturn retOrder = 0;
      retOrder = waitOrder_Server(socket,  mutexFile, folder);
      if(retOrder == SERVER_ERR || retOrder == SERVER_CLIENT_QUIT || retOrder == SERVER_QUIT)
	{
	  SocketFile sF;
	  initialize_SocketFile(&sF, NULL, socket);
	  while(delete_MutexFile(mutexFile, &sF) != MUTEXFILE_NOT_INSIDE);
	  
	  msg = "OLEH\n";
	  if(retOrder == SERVER_CLIENT_QUIT)
	    {
	      if(send_ToolsCS(socket, msg) != TOOLSCSRETURN_SUCCESS)
		{
		  fprintf(stderr, "[beginingDealing_Server]Erreur send_ToolsCS OLEH\n");
		}
	    }
	  shutdown(socket, SHUT_RDWR);
 	  close(socket);
	  testament_SocketFile(&sF);
	  return SERVER_CLIENT_QUIT;
	}
    }
  return SERVER_SUCCESS;
}

ServerReturn waitOrder_Server(int socket, MutexFile *mutexFile, char *folder)
{
  char *reception = NULL;
  ToolsCSReturn retRecv;
  ServerClientOrder cmd;
  char *response;
  ServerReturn sRet;

  retRecv = receive_ToolsCS(&reception, socket);
  if(retRecv == TOOLSCSRETURN_ERR)
    return SERVER_ERR;
  response = (char *) malloc ((7 + strlen(reception)) * sizeof(char));
  if(response == NULL)
    {
      fprintf(stderr, "[waitorder_Server]Erreur malloc\n");
      return SERVER_ERR;
    }
  sprintf(response, "RCPT %s\n", reception);
  if(send_ToolsCS(socket, response) == TOOLSCSRETURN_ERR)
    {
      fprintf(stderr, "[waitorder_Server]Erreur send_ToolsCS %s\n", response);
      free(response);
      free(reception);
      return SERVER_ERR;
    }
  free(response);
  cmd = orderString_Server(reception);
  switch(cmd)
    {
    case SERVERCLIENTORDER_LIST :
      if(sendList_Server(socket, folder) != SERVER_SUCCESS)
	{
	  fprintf(stderr, "[waitorder_Server]Erreur sendList_Server\n");
	  return SERVER_ERR;
	}
      break;
    case SERVERCLIENTORDER_GETF :
      sRet = sendGetF_Server(socket, reception, mutexFile, folder);
      if(sRet == SERVER_CON_ERR)
	{
	  free(reception);
	  fprintf(stderr, "[waitorder_Server]Information client has left\n");
	  return SERVER_ERR;
	}
      else if(sRet == SERVER_ERR)
	{
	  free(reception);
	  return SERVER_ERR;
	}
      break;
    case SERVERCLIENTORDER_FREE :
      receiveFree_Server(socket, reception, mutexFile, folder);
      break;
    case SERVERCLIENTORDER_ERR :
      if(send_ToolsCS(socket, "FAIL\n") == TOOLSCSRETURN_ERR)
	fprintf(stderr, "[waitorder_Server]Erreur send_ToolsCS FAIL\n");
      break;
    case SERVERCLIENTORDER_QUIT :
      free(reception);
      return SERVER_CLIENT_QUIT;
    default :
      free(reception);
      return SERVER_ERR;
    }

  free(reception);
  return SERVER_SUCCESS;
}

ServerReturn receiveFree_Server(int socket, char *reception, MutexFile *mutexFile, char *folder)
{
  MutexFileReturn mRet;
  SocketFile sf;
  char *file = NULL;
  if(strlen(reception) <= 6)
    {
      if(send_ToolsCS(socket, "FAIL\n") == TOOLSCSRETURN_ERR)
	fprintf(stderr, "[receiveFree_Server]Erreur send_ToolsCS FAIL\n");
      return SERVER_ERR;
    }
  reception += 5;
  reception[strlen(reception)] = '\0';
  if((*reception) == '\n' || (*reception) == '\0')
    {
      send_ToolsCS(socket, "FAIL\n");
      return SERVER_ERR;
    }

  if(g_file_test(reception, G_FILE_TEST_EXISTS) == FALSE)
    {
      file = (char *) malloc ((2 + strlen(reception) + strlen(folder)) * sizeof(char));

      sprintf(file, "%s/%s", folder, reception);
      if(g_file_test(file, G_FILE_TEST_EXISTS) == FALSE)
	{
	  free(file);
	  if(send_ToolsCS(socket, "FAIL\n") == TOOLSCSRETURN_ERR)
	    fprintf(stderr, "[receiveFree_Server]Erreur send_ToolsCS FAIL\n");
	  return SERVER_SUCCESS;
	}
    }
  else
    {
      file = (char *) malloc ((1 + strlen(reception)) * sizeof(char));
      strcpy(file, reception);
    }

  initialize_SocketFile(&sf, file, socket);
  mRet = delete_MutexFile(mutexFile, &sf);
  testament_SocketFile(&sf);
  free(file);
  if(mRet != MUTEXFILE_SUCCESS)
    {
      fprintf(stderr, "[receiveFree_Server]Erreur delete_MutexFile\n");
      if(send_ToolsCS(socket, "FAIL\n") == TOOLSCSRETURN_ERR)
	fprintf(stderr, "[receiveFree_Server]Erreur send_ToolsCS FAIL\n");
      return SERVER_ERR;
    }
  if(send_ToolsCS(socket, "FREE\n") == TOOLSCSRETURN_ERR)
    fprintf(stderr, "[receiveFree_Server]Erreur send_ToolsCS FREE\n");
  return SERVER_SUCCESS;
}

ServerReturn sendGetF_Server(int socket, char *reception, MutexFile *mutexFile, char *folder)
{
  MutexFileReturn mRet;
  SocketFile sF;
  char *file = NULL;

  if(strlen(reception) <= 6)
    {
      if(send_ToolsCS(socket, "FAIL\n") == TOOLSCSRETURN_ERR)
	fprintf(stderr, "[sendGetF_Server]Erreur send_ToolsCS FAIL\n");
      return SERVER_ERR;
    }  
  reception += 5;
  if((*reception) == '\n' || (*reception) == '\0')
    {
      if(send_ToolsCS(socket, "FAIL\n") == TOOLSCSRETURN_ERR)
	fprintf(stderr, "[sendGetF_Server]Erreur send_ToolsCS FAIL\n");
      return SERVER_ERR;
    }
    /* 
    Pour le test, cela ne fonctionne pas car le fichier lien.flv est dans le répertoire de test...
  */
  /*
  if(g_file_test(reception, G_FILE_TEST_EXISTS) == FALSE)
    {
  */
      file = (char *) malloc ((2 + strlen(reception) + strlen(folder)) * sizeof(char));

      sprintf(file, "%s/%s", folder, reception);
      if(g_file_test(file, G_FILE_TEST_EXISTS) == FALSE)
	{
	  free(file);
	  if(send_ToolsCS(socket, "NONE\n") == TOOLSCSRETURN_ERR)
	    fprintf(stderr, "[sendGetF_Server]Erreur send_ToolsCS NONE\n");
	  return SERVER_SUCCESS;
	}
      /*
    }
  else
    {
      file = (char *) malloc ((1 + strlen(reception)) * sizeof(char));
      strcpy(file, reception);
    }
      */
  initialize_SocketFile(&sF, file, socket);
  mRet = tryInsert_MutexFile(mutexFile, &sF);
  testament_SocketFile(&sF);
  if(mRet == MUTEXFILE_SUCCESS)
    {
      ServerReturn sRet;
      sRet = sendFile_Server(socket, file);
      if(sRet != SERVER_SUCCESS)
	{
	  fprintf(stderr, "[sendGetF_Server]Erreur sendFile_Server\n");
	  free(file);
	  return sRet;
	}
    }
  else if(mRet == MUTEXFILE_INSIDE)
    {
      if(send_ToolsCS(socket, "BUSY\n") == TOOLSCSRETURN_ERR)
	fprintf(stderr, "[sendGetF_Server]Erreur send_ToolsCS BUSY\n");
    }
  else
    {
      if(send_ToolsCS(socket, "FAIL\n") == TOOLSCSRETURN_ERR)
	fprintf(stderr, "[sendGetF_Server]Erreur send_ToolsCS FAIL\n");
      free(file);
      return SERVER_ERR;
    }
  free(file);
  return SERVER_SUCCESS;
}

ServerReturn sendList_Server(int socket, const char *folder)
{
  List list;
  char *message;
  getFile_FileManagement(&list, folder);
  first_List(&list);
  do
    {
      char *file = getDataCurrent_List(&list);
      message = (char *) malloc ((strlen(file) + strlen(folder) + 8) * sizeof(char));

      sprintf(message, "FICH %s\n", file);
      if(send_ToolsCS(socket, message) == TOOLSCSRETURN_ERR)
	{
	  fprintf(stderr, "[sendList_Server]Erreur send_ToolsCS %s\n", message);
	  free(message);
	  testament_List(&list);
	  return SERVER_ERR;
	}
      free(message);
    }while(next_List(&list) == LIST_SUCCESS);
  testament_List(&list);
  if(send_ToolsCS(socket, "ENDL\n") == TOOLSCSRETURN_ERR)
    {
      fprintf(stderr, "[sendList_Server]Erreur send_ToolsCS ENDL\n");
      return SERVER_ERR;
    }
  return SERVER_SUCCESS;
}

ServerReturn sendFile_Server(int socket, const char *file)
{
  FILE *fd;
  int sizeFile = 0;
  char buff[65536];
  int ret;
  FILE *f;
  char *message;
  fd = fopen(file, "rb");
  if(fd == NULL)
    {
      fprintf(stderr, "[sendFile_Server]Erreur ouverture %s\n", file);
      perror("");

      if(send_ToolsCS(socket, "SIZE 0\n") == TOOLSCSRETURN_ERR)
	{
	  fprintf(stderr, "[sendFile_Server]Erreur send_ToolsCS SIZE 0\n");
	  perror("");
	  return SERVER_CON_ERR;
	}
      return SERVER_ERR;
    }

  if(fseek(fd, 0, SEEK_END) != 0)
    {
      fprintf(stderr, "[sendFile_Server]Erreur fseek %s\n", file);
      perror("");

      if(send_ToolsCS(socket, "SIZE 0\n") == TOOLSCSRETURN_ERR)
	{
	  fprintf(stderr, "[sendFile_Server]Erreur send_ToolsCS SIZE 0\n");
	  perror("");
	  return SERVER_CON_ERR;
	}
      return SERVER_ERR;      
    }
  sizeFile = ftell(fd);
  if(sizeFile == - 1)
    {
      fprintf(stderr, "[sendFile_Server]Erreur ftell  %s\n", file);
      perror("");

      if(send_ToolsCS(socket, "SIZE 0\n") == TOOLSCSRETURN_ERR)
	{
	  fprintf(stderr, "[sendFile_Server]Erreur send_ToolsCS SIZE 0\n");
	  perror("");
	  return SERVER_CON_ERR;
	}
      return SERVER_ERR;
    }
  
  f = fopen(DEVNULL, "w");
  if(f == NULL)
    {
      if(send_ToolsCS(socket, "SIZE 0\n") == TOOLSCSRETURN_ERR)
	{
	  fprintf(stderr, "[sendFile_Server]Erreur send_ToolsCS SIZE 0\n");
	  perror("");
	  return SERVER_CON_ERR;
	}
      return SERVER_ERR;
    }
  ret = fprintf(f, "%d", sizeFile);
  fclose(f);
  message = (char *) malloc ((7 + ret) * sizeof(char));
  sprintf(message, "SIZE %d\n", sizeFile);
  if(send_ToolsCS(socket, message) == TOOLSCSRETURN_ERR)
    {
      free(message);
      fprintf(stderr, "[sendFile_Server]Erreur send_ToolsCS %s\n", message);
      perror("");
      return SERVER_CON_ERR;
    }
  free(message);
  rewind(fd);
  fprintf(stderr, "(sendFile_Server)Information début du téléchargement\n");
  while(feof(fd) == 0)
    {
      ret = fread(buff, 1, 65535, fd);
      ret = send(socket, &(buff), ret * sizeof(char), 0);
      if(ret == -1)
	{
	  fprintf(stderr, "[sendFile_Server]Erreur send buffer\n");
	  perror("");
	  return SERVER_CON_ERR;
	}
      /*
      if(recv(socket, buff, 4*sizeof(char), MSG_DONTWAIT) == 4)
	{
	  buff[4] = '\0';
	  if(strncmp(buff, "STOP", 4) == 0)
	    {
	      printf("Le client %d a arrêté le transfert\n", socket);
	      break;
	    }
	  else
	    {
	      printf("Le client %d s'amuse\n", socket);
	    }
	}
      */
    }
  fprintf(stderr, "(sendFile_Server)Information fin du téléchargement\n");
  if(fclose(fd) == -1)
    {
      fprintf(stderr, "[sendFile_Server]Erreur fclose\n");
      perror("");
      return SERVER_ERR;
    }
  return SERVER_SUCCESS;
}

ServerClientOrder orderString_Server(const char *reception)
{
  if(reception == NULL)
    return SERVERCLIENTORDER_ERR;
  if(strncmp(reception, "LIST", 4) == 0)
    {
      if(strlen(reception) == 4)
	return SERVERCLIENTORDER_LIST;
    }
  else if(strncmp(reception, "GETF", 4) == 0)
    return SERVERCLIENTORDER_GETF;
  else if(strncmp(reception, "FREE", 4) == 0)
    return SERVERCLIENTORDER_FREE;
  else if(strncmp(reception, "QUIT", 4) == 0)
    return SERVERCLIENTORDER_QUIT;
  return SERVERCLIENTORDER_ERR;
}
